// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: MIT

package metrics

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"os"
	"regexp"
	"strings"
	"time"

	"uos_uwsgi_exporter/pkg/errors"
	"uos_uwsgi_exporter/pkg/utils"
)

// 常量定义
const (
	// uWSGI stats 协议相关
	uwsgiStatsRequest = ""              // uWSGI stats 请求（空字符串）
	maxResponseSize   = 1024 * 1024 * 5 // 最大响应大小 5MB
	readBufferSize    = 4096            // 读取缓冲区大小

	// 连接重试相关
	maxRetries    = 3
	retryInterval = 100 * time.Millisecond
)

// TCP地址格式正则表达式
var (
	// IPv4:port 格式
	ipv4PortRegex = regexp.MustCompile(`^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+)$`)
	// IPv6:port 格式
	ipv6PortRegex = regexp.MustCompile(`^\[([^\]]+)\]:(\d+)$`)
	// hostname:port 格式
	hostPortRegex = regexp.MustCompile(`^([a-zA-Z0-9.-]+):(\d+)$`)
)

// uWSGIStats uWSGI统计信息结构
type uWSGIStats struct {
	Version           string                 `json:"version"`
	ListenQueue       int                    `json:"listen_queue"`
	ListenQueueErrors int                    `json:"listen_queue_errors"`
	SignalQueue       int                    `json:"signal_queue"`
	Load              int                    `json:"load"`
	PID               int                    `json:"pid"`
	UID               int                    `json:"uid"`
	GID               int                    `json:"gid"`
	Cores             int                    `json:"cores"`
	Workers           []WorkerStats          `json:"workers"`
	Apps              []AppStats             `json:"apps"`
	Sockets           []interface{}          `json:"sockets"`
	Cache             map[string]interface{} `json:"cache"`
	Locks             []interface{}          `json:"locks"`
	Shared            map[string]interface{} `json:"shared"`
	Mule              []interface{}          `json:"mule"`
	Spooler           []interface{}          `json:"spooler"`
	SNMP              map[string]interface{} `json:"snmp"`
	Stats             map[string]interface{} `json:"stats"`
}

// WorkerStats Worker统计信息
type WorkerStats struct {
	ID            int    `json:"id"`
	PID           int    `json:"pid"`
	Requests      int    `json:"requests"`
	Exceptions    int    `json:"exceptions"`
	Status        string `json:"status"`
	RSS           int    `json:"rss"`
	VSZ           int    `json:"vsz"`
	RunningTime   int    `json:"running_time"`
	LastSpawn     int    `json:"last_spawn"`
	RespawnCount  int    `json:"respawn_count"`
	HarakiriCount int    `json:"harakiri_count"`
	Signals       int    `json:"signals"`
	SignalQueue   int    `json:"signal_queue"`
	Cheap         int    `json:"cheap"`
	Busy          int    `json:"busy"`
	Accepting     int    `json:"accepting"`
	DeltaRequests int    `json:"delta_requests"`
	Weight        int    `json:"weight"`
	AvgRt         int    `json:"avg_rt"`
	Tx            int    `json:"tx"`
	Rx            int    `json:"rx"`
	Qlen          int    `json:"qlen"`
	QlenErrors    int    `json:"qlen_errors"`
	QlenMax       int    `json:"qlen_max"`
	QlenMaxErrors int    `json:"qlen_max_errors"`
}

// AppStats 应用统计信息
type AppStats struct {
	ID                int    `json:"id"`
	Modifier1         int    `json:"modifier1"`
	MountPoint        string `json:"mount_point"`
	StartupTime       int    `json:"startup_time"`
	Requests          int    `json:"requests"`
	Exceptions        int    `json:"exceptions"`
	Chdir             string `json:"chdir"`
	Script            string `json:"script"`
	Callable          string `json:"callable"`
	MasterPID         int    `json:"master_pid"`
	WorkerPID         int    `json:"worker_pid"`
	Chroot            string `json:"chroot"`
	Virtualenv        string `json:"virtualenv"`
	PythonPath        string `json:"python_path"`
	PythonVersion     string `json:"python_version"`
	PythonHome        string `json:"python_home"`
	PythonExecutable  string `json:"python_executable"`
	PythonPrefix      string `json:"python_prefix"`
	PythonLib         string `json:"python_lib"`
	PythonSite        string `json:"python_site"`
	PythonVersionInfo []int  `json:"python_version_info"`
}

// uWSGIClient uWSGI客户端
type uWSGIClient struct {
	socket     string
	socketType string
	timeout    time.Duration
}

// NewuWSGIClient 创建新的uWSGI客户端
func NewuWSGIClient(socket, socketType string, timeout time.Duration) *uWSGIClient {
	return &uWSGIClient{
		socket:     socket,
		socketType: socketType,
		timeout:    timeout,
	}
}

// GetStats 获取uWSGI统计信息
func (c *uWSGIClient) GetStats() (*uWSGIStats, error) {
	// 创建带超时的上下文
	ctx, cancel := context.WithTimeout(context.Background(), c.timeout)
	defer cancel()

	// 获取连接，支持重试
	conn, err := c.connectWithRetry(ctx)
	if err != nil {
		return nil, errors.NewConnectionError(c.socket, "connect", err).
			WithContext("timeout", c.timeout.String()).
			WithContext("socket_type", c.socketType)
	}
	defer conn.Close()

	// 发送统计请求
	if err := c.sendStatsRequest(ctx, conn); err != nil {
		if errors.IsTimeoutError(err) {
			return nil, errors.NewTimeoutError("send_stats_request", c.timeout, err).
				WithContext("socket", c.socket)
		}
		return nil, errors.NewSystemError("send_stats_request", err).
			WithContext("socket", c.socket).
			WithContext("socket_type", c.socketType)
	}

	// 读取并解析响应
	jsonData, err := c.readStatsResponse(ctx, conn)
	if err != nil {
		if errors.IsTimeoutError(err) {
			return nil, errors.NewTimeoutError("read_stats_response", c.timeout, err).
				WithContext("socket", c.socket)
		}
		return nil, errors.NewSystemError("read_stats_response", err).
			WithContext("socket", c.socket).
			WithContext("response_size", len(jsonData))
	}

	// 解析JSON响应
	var stats uWSGIStats
	if err := json.Unmarshal(jsonData, &stats); err != nil {
		return nil, errors.NewParserError("JSON", string(jsonData), err).
			WithContext("socket", c.socket).
			WithContext("data_size", len(jsonData))
	}

	return &stats, nil
}

// connectWithRetry 带重试的连接建立
func (c *uWSGIClient) connectWithRetry(ctx context.Context) (net.Conn, error) {
	var lastErr error

	for attempt := 0; attempt < maxRetries; attempt++ {
		if attempt > 0 {
			// 等待重试间隔
			select {
			case <-ctx.Done():
				return nil, ctx.Err()
			case <-time.After(retryInterval):
			}
		}

		conn, err := c.createConnection(ctx)
		if err == nil {
			return conn, nil
		}

		lastErr = err

		// 检查是否应该重试
		if !c.shouldRetryConnection(err) {
			break
		}
	}

	return nil, fmt.Errorf("failed after %d attempts: %w", maxRetries, lastErr)
}

// createConnection 创建连接
func (c *uWSGIClient) createConnection(ctx context.Context) (net.Conn, error) {
	network, address, err := c.parseSocketAddress()
	if err != nil {
		return nil, err
	}

	// 使用context控制的Dialer
	dialer := &net.Dialer{
		Timeout: c.timeout,
	}

	conn, err := dialer.DialContext(ctx, network, address)
	if err != nil {
		return nil, err
	}

	// 设置连接参数
	if err := c.configureConnection(conn); err != nil {
		conn.Close()
		return nil, fmt.Errorf("failed to configure connection: %w", err)
	}

	return conn, nil
}

// parseSocketAddress 解析socket地址
func (c *uWSGIClient) parseSocketAddress() (network, address string, err error) {
	switch c.socketType {
	case "unix":
		return "unix", c.socket, nil
	case "tcp":
		return "tcp", c.socket, nil
	default:
		// 自动检测socket类型
		return c.detectSocketType()
	}
}

// detectSocketType 检测socket类型
func (c *uWSGIClient) detectSocketType() (network, address string, err error) {
	// 使用统一的socket类型检测工具
	return utils.DetectSocketType(c.socket)
}

// configureConnection 配置连接参数
func (c *uWSGIClient) configureConnection(conn net.Conn) error {
	// 设置读写超时
	deadline := time.Now().Add(c.timeout)
	if err := conn.SetDeadline(deadline); err != nil {
		return fmt.Errorf("failed to set deadline: %w", err)
	}

	// 对于TCP连接，设置TCP特定选项
	if tcpConn, ok := conn.(*net.TCPConn); ok {
		// 设置无延迟
		if err := tcpConn.SetNoDelay(true); err != nil {
			return fmt.Errorf("failed to set TCP no delay: %w", err)
		}

		// 设置保活
		if err := tcpConn.SetKeepAlive(false); err != nil {
			return fmt.Errorf("failed to set TCP keep alive: %w", err)
		}
	}

	return nil
}

// sendStatsRequest 发送统计请求
func (c *uWSGIClient) sendStatsRequest(ctx context.Context, conn net.Conn) error {
	// uWSGI stats 协议：发送空字符串请求统计信息
	request := []byte(uwsgiStatsRequest)

	// 使用带超时的写入
	done := make(chan error, 1)
	go func() {
		_, err := conn.Write(request)
		done <- err
	}()

	select {
	case err := <-done:
		return err
	case <-ctx.Done():
		return ctx.Err()
	}
}

// readStatsResponse 读取统计响应
func (c *uWSGIClient) readStatsResponse(ctx context.Context, conn net.Conn) ([]byte, error) {
	// 使用带限制的reader防止内存耗尽
	limitedReader := io.LimitReader(conn, maxResponseSize)

	// 读取数据
	var response []byte
	buffer := make([]byte, readBufferSize)

	for {
		select {
		case <-ctx.Done():
			return nil, ctx.Err()
		default:
		}

		n, err := limitedReader.Read(buffer)
		if n > 0 {
			response = append(response, buffer[:n]...)
		}

		if err != nil {
			if err == io.EOF {
				break
			}
			return nil, fmt.Errorf("failed to read response: %w", err)
		}

		// 检查是否已经接收到完整的JSON
		if c.isCompleteJSON(response) {
			break
		}
	}

	// 提取JSON数据
	jsonData := c.extractJSON(response)
	if len(jsonData) == 0 {
		return nil, fmt.Errorf("no valid JSON data received from uWSGI stats socket")
	}

	return jsonData, nil
}

// isCompleteJSON 检查是否为完整的JSON
func (c *uWSGIClient) isCompleteJSON(data []byte) bool {
	if len(data) == 0 {
		return false
	}

	var braceCount int
	var jsonStarted bool

	for _, b := range data {
		if b == '{' {
			jsonStarted = true
			braceCount++
		} else if b == '}' && jsonStarted {
			braceCount--
			if braceCount == 0 {
				return true
			}
		}
	}

	return false
}

// extractJSON 提取JSON数据
func (c *uWSGIClient) extractJSON(data []byte) []byte {
	dataStr := string(data)

	// 查找JSON开始位置
	jsonStart := strings.Index(dataStr, "{")
	if jsonStart == -1 {
		return nil
	}

	// 从JSON开始位置计算大括号平衡
	var braceCount int
	var jsonEnd int = -1

	for i := jsonStart; i < len(dataStr); i++ {
		switch dataStr[i] {
		case '{':
			braceCount++
		case '}':
			braceCount--
			if braceCount == 0 {
				jsonEnd = i + 1
				goto found
			}
		}
	}

found:

	if jsonEnd == -1 {
		return nil
	}

	return []byte(dataStr[jsonStart:jsonEnd])
}

// shouldRetryConnection 判断是否应该重试连接
func (c *uWSGIClient) shouldRetryConnection(err error) bool {
	if err == nil {
		return false
	}

	errStr := err.Error()

	// 网络相关的临时错误可以重试
	if strings.Contains(errStr, "connection refused") ||
		strings.Contains(errStr, "network is unreachable") ||
		strings.Contains(errStr, "no route to host") ||
		strings.Contains(errStr, "timeout") {
		return true
	}

	// 系统资源相关错误可以重试
	if strings.Contains(errStr, "too many open files") ||
		strings.Contains(errStr, "resource temporarily unavailable") {
		return true
	}

	return false
}

// truncateData 截断数据用于错误显示
func (c *uWSGIClient) truncateData(data string, maxLen int) string {
	if len(data) <= maxLen {
		return data
	}
	return data[:maxLen] + "..."
}

// IsUnixSocket 检查是否为Unix socket
func (c *uWSGIClient) IsUnixSocket() bool {
	if c.socketType == "unix" {
		return true
	}

	if c.socketType == "tcp" {
		return false
	}

	// 自动检测
	return utils.IsUnixSocket(c.socket)
}

// IsTCPSocket 检查是否为TCP socket
func (c *uWSGIClient) IsTCPSocket() bool {
	if c.socketType == "tcp" {
		return true
	}

	if c.socketType == "unix" {
		return false
	}

	// 自动检测
	return utils.IsTCPAddress(c.socket)
}

// ValidateSocket 验证socket是否可访问
func (c *uWSGIClient) ValidateSocket() error {
	// 首先检测socket类型
	network, address, err := c.parseSocketAddress()
	if err != nil {
		return errors.NewValidationError("socket_address", c.socket, "invalid format").
			WithContext("socket", c.socket).
			WithContext("error", err.Error())
	}

	switch network {
	case "unix":
		return c.validateUnixSocket(address)
	case "tcp":
		return c.validateTCPSocket(address)
	default:
		return errors.NewValidationError("network_type", network, "must be unix or tcp").
			WithContext("socket", c.socket).
			WithContext("detected_network", network)
	}
}

// validateUnixSocket 验证Unix socket
func (c *uWSGIClient) validateUnixSocket(path string) error {
	// 检查文件是否存在
	info, err := os.Stat(path)
	if os.IsNotExist(err) {
		return errors.NewValidationError("socket_file", path, "file does not exist").
			WithContext("socket_type", "unix").
			WithContext("path", path)
	}
	if err != nil {
		return errors.NewSystemError("stat_socket_file", err).
			WithContext("socket_type", "unix").
			WithContext("path", path)
	}

	// 检查是否为socket文件
	if info.Mode()&os.ModeSocket == 0 {
		return errors.NewValidationError("file_type", "regular_file", "must be socket file").
			WithContext("socket_type", "unix").
			WithContext("path", path).
			WithContext("file_mode", info.Mode().String())
	}

	// 检查权限
	if info.Mode().Perm()&0o600 == 0 {
		return errors.NewValidationError("file_permissions", info.Mode().Perm().String(), "insufficient permissions").
			WithContext("socket_type", "unix").
			WithContext("path", path).
			WithContext("required_permissions", "0600")
	}

	return nil
}

// validateTCPSocket 验证TCP socket
func (c *uWSGIClient) validateTCPSocket(address string) error {
	// 解析主机和端口
	host, portStr, err := net.SplitHostPort(address)
	if err != nil {
		return errors.NewValidationError("tcp_address_format", address, "invalid host:port format").
			WithContext("socket_type", "tcp").
			WithContext("address", address).
			WithContext("error", err.Error())
	}

	if host == "" {
		return errors.NewValidationError("tcp_host", "", "host cannot be empty").
			WithContext("socket_type", "tcp").
			WithContext("address", address)
	}

	if portStr == "" {
		return errors.NewValidationError("tcp_port", "", "port cannot be empty").
			WithContext("socket_type", "tcp").
			WithContext("address", address)
	}

	// 验证端口范围
	if !c.isValidPort(portStr) {
		return errors.NewValidationError("tcp_port_range", portStr, "port must be between 1-65535").
			WithContext("socket_type", "tcp").
			WithContext("address", address).
			WithContext("port", portStr)
	}

	// 尝试解析主机名
	if err := c.validateHost(host); err != nil {
		return errors.NewValidationError("tcp_host_format", host, "invalid hostname or IP").
			WithContext("socket_type", "tcp").
			WithContext("address", address).
			WithContext("host", host).
			WithContext("error", err.Error())
	}

	return nil
}

// isValidPort 验证端口号
func (c *uWSGIClient) isValidPort(portStr string) bool {
	// 使用正则表达式验证端口格式
	portRegex := regexp.MustCompile(`^[0-9]+$`)
	if !portRegex.MatchString(portStr) {
		return false
	}

	// 检查端口范围 (1-65535)
	if len(portStr) > 5 {
		return false
	}

	// 简单的数值范围检查
	port := 0
	for _, r := range portStr {
		port = port*10 + int(r-'0')
		if port > 65535 {
			return false
		}
	}

	return port >= 1 && port <= 65535
}

// validateHost 验证主机名或IP地址
func (c *uWSGIClient) validateHost(host string) error {
	// 检查是否为IP地址
	if ip := net.ParseIP(host); ip != nil {
		return nil // 有效的IP地址
	}

	// 检查主机名格式
	if host == "localhost" {
		return nil
	}

	// 简单的主机名验证
	hostRegex := regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$`)
	if !hostRegex.MatchString(host) {
		return fmt.Errorf("invalid hostname format: %s", host)
	}

	return nil
}
